/* Copyright (c) 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.orkut.client.api.samples.greetings.client.ui;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.name.Named;
import com.google.orkut.client.api.samples.greetings.client.DataModel;
import com.google.orkut.client.api.samples.greetings.client.GreetingsCallbackWrapper;
import com.google.orkut.client.api.samples.greetings.client.GreetingsMessages;
import com.google.orkut.client.api.samples.greetings.client.DataModel.DataModelUpdateCallback;
import com.google.orkut.client.api.samples.greetings.client.selector.Item;
import com.google.orkut.client.api.samples.greetings.client.selector.ItemSelector;
import com.google.orkut.client.api.samples.greetings.client.selector.SearchBox;
import com.google.orkut.client.api.samples.greetings.client.services.AlbumInfo;
import com.google.orkut.client.api.samples.greetings.client.services.AlbumsServiceAsync;
import com.google.orkut.client.api.samples.greetings.client.services.UserInfo;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * A widget which displays albums and allows a user to select a given album.
 *
 * @author Shishir Birmiwal
 */
public class AlbumSelector extends ItemSelector<AlbumInfo>
implements DataModelUpdateCallback, AsyncCallback<ArrayList<AlbumInfo>> {
  private static final int MAX_ALBUM_NAME_LENGTH = 15;
  UserInfo selectedUser;
  private final AlbumsServiceAsync albumsService;
  private final String postToken;
  private final DataModel dataModel;
  private AlbumSelectedCallback cb;
  private final GreetingsMessages msgs;
  private final Provider<Item> itemsProvider;
  private final GreetingsCallbackWrapper cbWrapper;

  public static interface AlbumSelectedCallback {
    public void albumSelected(AlbumInfo album);
  }

  @Inject
  public AlbumSelector(
      SearchBox searchBox,
      @Named("postToken") String postToken,
      Provider<Item> itemsProvider,
      DataModel dataModel,
      GreetingsMessages msgs,
      GreetingsCallbackWrapper cbWrapper,
      AlbumsServiceAsync albumsService) {
    super(searchBox);
    this.postToken = postToken;
    this.itemsProvider = itemsProvider;
    this.dataModel = dataModel;
    this.msgs = msgs;
    this.cbWrapper = cbWrapper;
    this.albumsService = albumsService;
    dataModel.registerCallback(this);
  }

  public void setAlbumSelectedCallback(AlbumSelectedCallback cb) {
    this.cb = cb;
  }

  @Override
  public void update(DataModel data, Type type) {
    if (Type.SELECTED_USER.equals(type)) {
      updateUserInfo(data);
    }
    if (Type.ALBUMS.equals(type) || Type.SHARED_ALBUMS.equals(type)) {
      updateAlbumsInfo(data);
    }
  }

  private void updateAlbumsInfo(DataModel data) {
    HashMap<String, AlbumInfo> newAlbums = data.userAlbumInfo.get(selectedUser.id);
    ArrayList<AlbumInfo> newValues = new ArrayList<AlbumInfo>();
    updateItems(newValues);
    newValues.addAll(data.sharedAlbums);
    if (newAlbums != null) {
      newValues.addAll(newAlbums.values());
    }
    updateItems(newValues);
  }

  @Override
  protected Item getItemFor(final AlbumInfo album) {
    Item item = itemsProvider.get();
    item.setText(UserSelector.getClippedString(album.title, MAX_ALBUM_NAME_LENGTH) + "[" + album.numPhotos + "]");
    item.setIcon(album.thumbnailUrl);
    item.setTitle(album.title);
    item.setCallback(new Item.ItemSelectedCallback() {
      @Override
      public void selected(Item item) {
        if (cb != null) {
          cb.albumSelected(album);
        }
      }
    });
    return item;
  }

  private void updateUserInfo(DataModel data) {
    if (!data.selectedUser.equals(selectedUser)) {
      selectedUser = data.selectedUser;
      requestAlbums();
    }
  }

  private void requestAlbums() {
    albumsService.getAlbumsOf(postToken, selectedUser.id, cbWrapper.wrap(this));
    if (dataModel.sharedAlbums.isEmpty()) {
      albumsService.getSharedAlbums(postToken, cbWrapper.wrap(new AsyncCallback<ArrayList<AlbumInfo>>() {
        @Override
        public void onFailure(Throwable arg0) {
          Window.alert(msgs.errorFetchingAlbums());
        }

        @Override
        public void onSuccess(ArrayList<AlbumInfo> albums) {
          dataModel.updateSharedAlbums(albums);
        }
      }));
    }
  }

  @Override
  public void onFailure(Throwable caught) {
    Window.alert(msgs.errorFetchingAlbums());
  }

  @Override
  public void onSuccess(ArrayList<AlbumInfo> albums) {
    dataModel.addAlbums(albums);
  }
}
